package org.broadinstitute.hellbender.tools.spark.sv.discovery.inference;

import com.google.common.collect.Lists;
import htsjdk.samtools.SAMSequenceDictionary;
import htsjdk.samtools.TextCigarCodec;
import htsjdk.variant.variantcontext.VariantContext;
import htsjdk.variant.variantcontext.VariantContextBuilder;
import org.broadinstitute.hellbender.GATKBaseTest;
import org.broadinstitute.hellbender.tools.spark.sv.discovery.alignment.AlignedContig;
import org.broadinstitute.hellbender.tools.spark.sv.discovery.alignment.AlignmentInterval;
import org.broadinstitute.hellbender.tools.spark.sv.discovery.alignment.AssemblyContigWithFineTunedAlignments;
import org.broadinstitute.hellbender.tools.spark.sv.discovery.alignment.ContigAlignmentsModifier;
import org.broadinstitute.hellbender.tools.spark.sv.utils.GATKSVVCFConstants;
import org.broadinstitute.hellbender.utils.SimpleInterval;
import org.broadinstitute.hellbender.testutils.VariantContextTestUtils;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import scala.Tuple2;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static org.broadinstitute.hellbender.tools.spark.sv.discovery.TestUtilsForAssemblyBasedSVDiscovery.*;
import static org.broadinstitute.hellbender.tools.spark.sv.StructuralVariationDiscoveryArgumentCollection.DiscoverVariantsFromContigAlignmentsArgumentCollection.GAPPED_ALIGNMENT_BREAK_DEFAULT_SENSITIVITY;


public class CpxVariantInterpreterUnitTest extends GATKBaseTest {

    private static final class ValidLocalData {
        final AlignmentInterval one;
        final AlignmentInterval two;
        final int overlapOnRead;
        final boolean expectedOneShouldYieldToTwo;
        final Boolean hintRequestYieldingOverlapToAlignmentTwo;
        final Tuple2<AlignmentInterval, AlignmentInterval> expectedDeOverlapedAlignments;

        ValidLocalData(final AlignmentInterval one, final AlignmentInterval two,
                       final int overlapOnRead,
                       final boolean expectedOneShouldYieldToTwo,
                       final Boolean hintRequestYieldingOverlapToAlignmentTwo,
                       final Tuple2<AlignmentInterval, AlignmentInterval> expectedDeOverlapedAlignments) {
            this.one = one;
            this.two = two;
            this.overlapOnRead = overlapOnRead;
            this.expectedOneShouldYieldToTwo = expectedOneShouldYieldToTwo;
            this.hintRequestYieldingOverlapToAlignmentTwo = hintRequestYieldingOverlapToAlignmentTwo;
            this.expectedDeOverlapedAlignments = expectedDeOverlapedAlignments;
        }
    }

    private final List<ValidLocalData> validInputs = validInputsToOverlapYieldingStrategy();

    @BeforeTest
    private static List<ValidLocalData> validInputsToOverlapYieldingStrategy() {
        final List<ValidLocalData> data = new ArrayList<>(20);

        new AlignmentInterval(new SimpleInterval("chr1", 202317371, 202317402), 1104, 1135, TextCigarCodec.decode("1085H18S32M1393H"), false, 60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS, ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL);

        // from a 3-alignment real event, here we have the first two alignments, though the second alignment should yield overlap to first when considering the whole contig, here we are reusing them for case that higher chr should yield to lower chr
        data.add(new ValidLocalData(fromSAMRecordString("asm004677:tig00000\t2064\tchr3\t15737523\t60\t1425H377M1D726M\t*\t0\t0\tAGAGCAATCATAGCTCACCGTAACTTCAAATTCCTTGGCTTAAGTGATCCTCCCACCTTTGCTTCCTGAGTAGCTAGGACTACAGGTGCATGCCACCACCCCTGGCTAATTTTTTAGTTATTTTGTAGAGACAAGGTCTTGCTATGTTGCCCAGGCTGGTCTCAAACTCCTGGCCTCAAGTGATTCTCCTTCCTTGGCCTCCTGAAGTGTTGGGGTTACAAACATGAGCCAGTCATAGAGCCACACCTGGCTCTTTGAACAATTTTAAGCAATAGATTTTTTACACTGCATATATAAAAATTAAAAACATACTATTTCTCAATGTATTATACATGCTATATTTGACAAAATGAAAAATCACTAGGATCAATTTCATTAAAAAAAAAAAAAGACACAACATAGACAAGGTTCTTTTTGCAGTGCTGCTTAGAGAGAAAGTTAAGGCAATTTAAGAGTCTACTGTCCAAGGGATTTATCTCCCAGAAGCGCATGGAAAACATCACAACACTACCTCTATAAATTGGACTCATGGCAGGATTCCAAGGAATTCAGTATGCCATCAACATTAAGCAATATAATCAGAACTAAACTCAACAAAATTTTTCTTTCAGTGATAATCCTAATTTTTGGTAAATTATCGGGGAACCTGCCCCCAATAATTCAAAGTGAGTCCTTTTCTATTTTCCCTAAGTGTCGGCTGGTCTGAGAAATAAAGGGAAAGAGTACAAAAGAGAGAAATTTTAAAGCTGGGTGTCTGGGGAGACATCACATGCCCAAGCCGCAAAACCAGCAAGTTTTTATTAGTGATTTTCAAAAGGGGAGGGAGAGTACGAATAGGGTATGAGTCACAGAGATCACATGCTTCACAAGGTAATAAAATATTACAAGGCAAATGGAGGCAGGGCGAGATCACAGGACCAGGTGAAATTAACATTGCTAATGAAGTTTTGGGCACACATTGTCATTGATAACATCTTATCAGGAGACAGGGGCCGGGCACAGTGGCGCGTGCCTGTAGTCCCAGCTACTCGGGAGGCTGAGGTGGGAGGATCGCTTGAGCCCAGGAGTTCTGGGCTGTAGTGCGCTATGCCGATCGGGTGTCC\t*\tSA:Z:chr3,15736242,-,1282M1246S,60,0;chr1,202317371,-,1393S50M1085S,60,1;\tMD:Z:164C19C192^A449T276\tRG:Z:GATKSVContigAlignments\tNM:i:4\tAS:i:1071\tXS:i:161", true),
                                    fromSAMRecordString("asm004677:tig00000\t2064\tchr1\t202317371\t60\t1393H50M1085H\t*\t0\t0\tGTCTTGCTCTGTTGCCCAGGCTGGAGTGCAGTAGAGCAATCATAGCTCAC\t*\tSA:Z:chr3,15736242,-,1282M1246S,60,0;chr3,15737523,-,1425S377M1D726M,60,4;\tMD:Z:41T8\tRG:Z:GATKSVContigAlignments\tNM:i:1\tAS:i:45\tXS:i:0", true),
                                    18, true,  null,
                                    new Tuple2<>(new AlignmentInterval(new SimpleInterval("chr3", 15737541, 15738626), 1, 1085, TextCigarCodec.decode("726M1D359M18S1425H"), false, 60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS, ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL),
                                                 new AlignmentInterval(new SimpleInterval("chr1", 202317371, 202317420), 1086, 1135, TextCigarCodec.decode("1085H50M1393H"), false, 60, 1, 45, ContigAlignmentsModifier.AlnModType.NONE))
        ));

        // DEL '+'-rep
        data.add(new ValidLocalData(fromSAMRecordString("asm016186:tig00003\t2048\tchr10\t6055203\t60\t221M1064H\t*\t0\t0\tAAATGCATTAAAGGTTGAGAAGTACTGCTTGAGCATACCTGTTCCTAGTGAATCAGACCAACCATGGAAATCATTATTCCATCTCTCTAATTTGGTGAGTTTCAATCCTAAGTGCGATTTGGAAGTATTCAAGGAACTGGAAGGGAAGGTATTGTGATGTTCGGTTCTGTTCCCCAGAGAGTCCGCTTAATTCATCTTATGAGTCTTGGCCATCACTTTTT\t*\tSA:Z:chr10,6055906,+,205S1080M,60,0;\tMD:Z:221\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:221\tXS:i:0", true),
                                    fromSAMRecordString("asm016186:tig00003\t0\tchr10\t6055906\t60\t205S1080M\t*\t0\t0\tAAATGCATTAAAGGTTGAGAAGTACTGCTTGAGCATACCTGTTCCTAGTGAATCAGACCAACCATGGAAATCATTATTCCATCTCTCTAATTTGGTGAGTTTCAATCCTAAGTGCGATTTGGAAGTATTCAAGGAACTGGAAGGGAAGGTATTGTGATGTTCGGTTCTGTTCCCCAGAGAGTCCGCTTAATTCATCTTATGAGTCTTGGCCATCACTTTTTAAAGCATCCTGGATATACACTAATGTACAGCTGGCGTTTTGAACCATTACTCTCCACACATTTCCCAGTGGGAACTGTGTTTTCTTTTTGACAGAAGCAAACCACGGAGTCGCCTTGAGATCAGTCAAAACACTGAGTAATCTTAGAGTGGAGAATACCTAAAATTTCTAGAGACAATTATATTATTGTTTTCCCCTAAATGAGTGAGTTACTTGAGAATATGGTGGGGTATTCAGTGGGGGCTATTGGCAAACACTGTTGGCTGACTTCAGAATGGGAGCCATTCAGCAGCAGTTTCATCTCCCGTGTTAAACTGTGAGCACAAGAGGATAAGAGCTGGAACTTTCTTCATCTCTGTAATCCTCATGCATGAATGGATGGATGAAGGAATATCACTGAGAATTCATGTAAAGATGTGCAGATGTGCAGGGAATATTGAACTGAAATTTAAGAGGGCTGGATTCAAGTTCAGCTTCTATGTGAACTCTTTCAGTGAAGAAGGTCTTATAACTTTTAGAAGTAATCAACTGAATTAAGATTCTCTTTTCAGCTGGGCACAGTGGCTCATGCCTGTAATCCCAGCACTTTGGAAGGCCCATGCAGATGGATGGCTTGAGGCTCGGAGTTCAAGACCAGCCTACGCAACATAGCAAAAACCCCCTCTCTACTAAAATTACAAAAAAGGAGCCAGGCATGGTGGTGCACACCTGTAATCCCAGCTACTCAGGAGACAGAGGCAGGAGAATCACTTGAACCCAGGAGCTGAAGGTTGCAGTGAGTTGAGATTGCACCACTGTGCTCTAGCCTGGGCGACAGAGCGAAACTGTCCAAAAAAAAAAAAGATTCCCCTTTCTCTTCTCTCAGGGAATGGCCTGGGATAGAGAAGAGAAACAGGTTCCCACTCATGTAAAACTTCTCCCATGGGAGACAAGGACATTGTTTGAGGGGAAAATTCCTACACAAGCAAACAAACAGCAGAGGACCCCGCCCTCCCTGTCCAGGGCAGGAGCACAGTGGACCACCTGCTGCCCCTGTGTCTTGGGGCCTCTCTCCCTGGAATGTCA\t*\tSA:Z:chr10,6055203,+,221M1064S,60,0;\tMD:Z:1080\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:1080\tXS:i:39", true),
                              16, true, null,
                                    new Tuple2<>(new AlignmentInterval(new SimpleInterval("chr10", 6055203, 6055407), 1, 205, TextCigarCodec.decode("205M16S1064H"), true, 60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS, ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL),
                                                 new AlignmentInterval(new SimpleInterval("chr10", 6055906, 6056985), 206, 1285, TextCigarCodec.decode("205S1080M"), true, 60, 0, 1080, ContigAlignmentsModifier.AlnModType.NONE))
        ));

        // DEL '-'-rep
        data.add(new ValidLocalData(fromSAMRecordString("asm011675:tig00000\t2064\tchr7\t5803446\t60\t1046H558M\t*\t0\t0\tATATGTTTCCATGATTTCCATGAGGAAGGCATGTGCTCTGTCCCTTTCTTCCCAATGCTCACTGCGTCTTTTTTTTTTTAATAGACTTGACTTTTTTAGGCCAGTTTTAGATTCGTAGCAACATTGAGCGAAAGGTACAGAGAGTTCTCACATGTTCCCTGCCCGTGCTAATAGCCTCTCCCATTATCATCTTCCACCAAAGTGGTACATTTGTTACAATCAGGGAACCTATATTGACATCATTTTCACCCAAAGTCCACAGTTTGCATTAGGGTCCCTCTTGGTGTGGTGCATGTCATGGGCTTGGATAAATGTGTCAGAACATGCATCCACTGTTAGAGCTCTCTCAGAGGCGTTTCCCTGCCCGAAAAATCCTCCGTGCTCTGCCTCTTCATGCATCCCTCCCTTCATGCATCCGTCCCAGGGACAAAAGGTTGTCCCTGGCAACCTTTTGTTTCCAGACCCTAGCAACGGATCCTTTTACTGTCTCCATAGTTGGGCCTTTTCTGAATGTAATATAGTTGGAATCATACAGCATTAATTTTTTTTTTCCACTGA\t*\tSA:Z:chr7,5802154,-,1009M1D120M475S,60,4;\tMD:Z:8G325C223\tRG:Z:GATKSVContigAlignments\tNM:i:2\tAS:i:548\tXS:i:0", true),
                                    fromSAMRecordString("asm011675:tig00000\t16\tchr7\t5802154\t60\t1009M1D120M475S\t*\t0\t0\tATATTTTCTGAGATTTATAAGCTTTTTTAAAAAATTAAGGGCTGGGCACAGTGGTTCACACTTGTAAGTGCAGCACTTTGGGAGGCTAAGGCAGGAGGATTGATTGAGGTCAGGAGTTGGAGGCTACAGTGAGCTATGATTGCACCACTGCACTCTAGCCTGGGAGACAGAGTGAGACCCTGACTCAAACAGTAATTAAATCAATAAAATTTAGAAGTTAAGATTCTTCAGCCTCTTTTGGGCTGGGCATGGTCGCTCAAGCTTGTAATCCCAGCACTCTGGGAGGCTGTGGCAGGCTGATCACTTGAGGCCAGGAGTTTGAGACCAACCTGGCCAACATTGTGAAACCCCATCTCTACTAAAAATACAGAAATTAGCCGGTGTGGTGATGCATGCCTGTAATCCCAGCTGTTCAGGAGGCTGAGACAGGAGAATTGCTTGAACTCGGGAGGTGGAGGTTGCAGTGAGCTGAGAGCATGTCACTCTATTCCAGCCCGGGCGACAGAACTAGACTCCGTCTCAAAAAAAAAAAAAAAAAGATTCTTCAGTCTCTTTTGATCTTCCTGTGCCCACTTTATGGTGCCCGGAGCTGCTGATGTTCAGATTTGCCATGGGCGGTGCTCCCCTACATCTGAAGATGCAAAGATCTCTCTTCTTCCTTGTCACCTAATCCTGCTGGCCTTCTCAGGCTCATCTGCAGAAGACCCCACTCAAAAGTAGGGTCTGGCCAGCTGCGGTGGCTCACGCTTGTAATCCCAGCACTTTGGGAGGCTGAGGCAGGTGGGATCACCTGAGGTCAGGAGTTCAAGAACAGCCTGACCAATGTGGCGAAACCCTGTCTCTACTAAAAAATACCAAAATTAGCCAGGCGTAGTGGTGGGCGCCTATAACCCCATCTACTCGGGAGGCTGAGGCTGGAGAATAGCTTGAACCTGGGGGTTGAAGGTTGCAGTGAGTCAAGATGATGCCACTGCACTCCAGTCTGGGTGAAAGAGCAAAACTCCATCTCAAAAAAAAAAAAAAAAAGGGGGGGTCTTCTTCAGAAGATATGTTTCCATGATTTCCATGAGGAAGGCATGTGCTCTGTCCCTTTCTTCCCAATGCTCACTGCGTCTTTTTTTTTTTAATAGACTTGACTTTTTTAGGCCAGTTTTAGATTCGTAGCAACATTGAGCGAAAGGTACAGAGAGTTCTCACATGTTCCCTGCCCGTGCTAATAGCCTCTCCCATTATCATCTTCCACCAAAGTGGTACATTTGTTACAATCAGGGAACCTATATTGACATCATTTTCACCCAAAGTCCACAGTTTGCATTAGGGTCCCTCTTGGTGTGGTGCATGTCATGGGCTTGGATAAATGTGTCAGAACATGCATCCACTGTTAGAGCTCTCTCAGAGGCGTTTCCCTGCCCGAAAAATCCTCCGTGCTCTGCCTCTTCATGCATCCCTCCCTTCATGCATCCGTCCCAGGGACAAAAGGTTGTCCCTGGCAACCTTTTGTTTCCAGACCCTAGCAACGGATCCTTTTACTGTCTCCATAGTTGGGCCTTTTCTGAATGTAATATAGTTGGAATCATACAGCATTAATTTTTTTTTTCCACTGA\t*\tSA:Z:chr7,5803446,-,1046S558M,60,2;\tMD:Z:516A337T154^A45G74\tRG:Z:GATKSVContigAlignments\tNM:i:4\tAS:i:1097\tXS:i:1029", true),
                              123, false, null,
                                    new Tuple2<>(new AlignmentInterval(new SimpleInterval("chr7", 5803446, 5804003), 1, 558, TextCigarCodec.decode("558M1046H"), false, 60, 2, 548, ContigAlignmentsModifier.AlnModType.NONE),
                                                 new AlignmentInterval(new SimpleInterval("chr7", 5802154, 5803159), 599, 1604, TextCigarCodec.decode("598S1006M"), false, 60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS, ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL))
        ));

        // INV55 '+'-rep
        data.add(new ValidLocalData(fromSAMRecordString("asm000295:tig00009\t0\tchr1\t13235227\t60\t570M151S\t*\t0\t0\tGGATTACAGGCGTGAGCCACCGCGCCCGGCCGGGGGACTCTATCTCAAAAAAAAAAAAAAAAAATTCAGTAGTAAAACTTTTGGTTAGCAGGGCACGGCTGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCAGATCATGAGGTCAGGAGATCGACACCATCCTGGCTAACATGGTGAAACCGCATCTCTACTAAAAATAGAAAAAAAATTAGCCAGGCGTGGTGGCAGGTGCCTGTAGTCCCAGCTACTCAGGAGGCTGAGGCGGGAGAATGGCATGAACCCAGGAGGCAGAGCTTGCAGTGAGCCAAGATCATGCCACTGCACTCCAGCCTCGGTGACAGAGCAAGACTCCGTCTCAAAAATAAAAAACAAAAAAAAACTTTCGGTTAGTGTAATCTAGTCTTCCCTGTAGATGTAGCTAATTTTATTTTATTTTTATTATTATTTTTATTGAGACAGAGTCTTCCTCTGTCTGCCAGACCGGAGTACAATGGTGCGATCTCGGCTCACTGCAACCTCCATCTCCCGAGTTCAAGCGATTCTCCTGCCTCAGCCTCCTGAGTGGCTGGGATTACAAATGTGCACCACCACGCTTTGCTAAGTTTTGTATTTTTACTAGAGACAGCGTTTCCCATGTTGCCCAGGCTGGTCTTGAACTTGTGATCTCTGGTGATCTGCCCACCTCGGCCTCCCAAAGTTGTTGGGAGTG\t*\tSA:Z:chr1,13384970,-,218M503S,60,1;\tMD:Z:531T0G0C4T1G7T15A5\tRG:Z:GATKSVContigAlignments\tNM:i:7\tAS:i:535\tXS:i:0", true),
                                    fromSAMRecordString("asm000295:tig00009\t2064\tchr1\t13384970\t60\t218M503H\t*\t0\t0\tCACTCCCAACAACTTTGGGAGGCCGAGGTGGGCAGATCACCAGAGATCACAAGTTCAAGACCAGCCTGGGCAACATGGGAAACGCTGTCTCTAGTAAAAATACAAAACTTAGCAAAGCGTGGTGGTGCACATTTGTAATCCCAGCCACTCAGGAGGCTGAGGCAGGAGAATCGCTTGAACTCGGGAGATGGAGGTTGCAGTGAGCCGAGATCGCACCA\t*\tSA:Z:chr1,13235227,+,570M151S,60,7;\tMD:Z:212A5\tRG:Z:GATKSVContigAlignments\tNM:i:1\tAS:i:213\tXS:i:0", true),
                              67, true, null,
                                    new Tuple2<>(new AlignmentInterval(new SimpleInterval("chr1", 13235227, 13235729), 1, 503, TextCigarCodec.decode("503M218S"), true, 60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS, ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL),
                                                 new AlignmentInterval(new SimpleInterval("chr1", 13384970, 13385187), 504, 721, TextCigarCodec.decode("503H218M"), false, 60, 1, 213, ContigAlignmentsModifier.AlnModType.NONE))
        ));

        // INV55 '-'-rep
        data.add(new ValidLocalData(fromSAMRecordString("asm001039:tig00012\t2048\tchr1\t81195731\t60\t143M145H\t*\t0\t0\tTCACTAAATTCAGTACATACTCAAGGAATGAGGAAGCAAGCTCCCCCCTCCTGGAGGAAGGAGTATCAAATATCTTGTAATAATTAATAAATATTTGAAGGTAGACATTTTGAGGCTATGCCGATATCCTGTTTTTCTTTAAA\t*\tSA:Z:chr1,81194519,-,148M140S,60,0;\tMD:Z:122A20\tRG:Z:GATKSVContigAlignments\tNM:i:1\tAS:i:138\tXS:i:22", true),
                                    fromSAMRecordString("asm001039:tig00012\t16\tchr1\t81194519\t60\t148M140S\t*\t0\t0\tTCTAAAAACTGCTAAGAAACTCAAGTTTTCTGAAGTGGTCTGTTCGGAGGTTTGTGCATTTTTCAGTGATCTGTAACAATGTATTTTTCTTCCCACCATCTACTGCAGGTGGGTTCACAGGTGGGACCTGAGGAGCATTTGGGGATTTAAAGAAAAACAGGATATCGGCATAGCCTCAAAATGTCTACCTTCAAATATTTATTAATTATTACAAGATATTTGATACTCCTTCCTCCAGGAGGGGGGAGCTTGCTTCCTCATTCCTTGAGTATGTACTGAATTTAGTGA\t*\tSA:Z:chr1,81195731,+,143M145S,60,1;\tMD:Z:148\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:148\tXS:i:19", true),
                              3, false, null,
                                    new Tuple2<>(new AlignmentInterval(new SimpleInterval("chr1", 81195731, 81195873), 1, 143, TextCigarCodec.decode("143M145H"), true, 60, 1, 138, ContigAlignmentsModifier.AlnModType.NONE),
                                                 new AlignmentInterval(new SimpleInterval("chr1", 81194519, 81194663), 144, 288, TextCigarCodec.decode("143S145M"), false, 60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS, ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL))
        ));

        // INV33 '+'-rep
        data.add(new ValidLocalData(fromSAMRecordString("asm000619:tig00014\t2064\tchr1\t34802227\t60\t149H126M\t*\t0\t0\tGGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTTGGTTT\t*\tSA:Z:chr1,54510617,+,75S200M,60,0;\tMD:Z:126\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:126\tXS:i:0", true),
                                    fromSAMRecordString("asm000619:tig00014\t0\tchr1\t54510617\t60\t75S200M\t*\t0\t0\tAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCAAACCCGAAAAACAAACTAAAAAACCCCACAAAAACAAACAAAACAAAATGCAGTGTATTTGGAGAGAACGGGTGTCTGGTTATTTTGTGCTTTGTATCAAGTTAGCCCAAAACTTAGTGGCATAAAACAATCAAGCATTGTGCTCGCAGATTAT\t*\tSA:Z:chr1,34802227,-,149S126M,60,0;\tMD:Z:200\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:200\tXS:i:22", true),
                              51, false, null,
                                    new Tuple2<>(new AlignmentInterval(new SimpleInterval("chr1", 34802227, 34802352), 1, 126, TextCigarCodec.decode("126M149H"), false, 60, 0, 126, ContigAlignmentsModifier.AlnModType.NONE),
                                                 new AlignmentInterval(new SimpleInterval("chr1", 54510668, 54510816), 127, 275, TextCigarCodec.decode("126S149M"), true, 60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS, ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL))
        ));

        // INV33 '-'-rep
        data.add(new ValidLocalData(fromSAMRecordString("asm016915:tig00033\t16\tchr10\t73660151\t60\t140S145M\t*\t0\t0\tCCTTTCTCTGGATCTCATCTGGAATTGGCCTCACAGTTTGTGAACAGCCCAGAAATAGCCAATGTCTTAGCTTTGGAACGTTTGCCACTTTCCAGCTACAGCTGGACCTTGTATCCTGGTTTGGTTCCTGATGACTTTCAAAGAACAAATGGCTTCCAGCAAGAGAAAAAGGGGATGCAACATTTTTACAAATTATTTCTTTTTTTATTAAAAAAATTTTAAGTTAAATGCTAAAGATATGTTTAACCTCTCTGATACTGACTTGCTCATGAGAAGAAAGAGAGA\t*\tSA:Z:chr10,73659956,+,143S142M,60,0;\tMD:Z:145\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:145\tXS:i:74", true),
                                    fromSAMRecordString("asm016915:tig00033\t2048\tchr10\t73659956\t60\t143H142M\t*\t0\t0\tTTTGAAAGTCATCAGGAACCAAACCAGGATACAAGGTCCAGCTGTAGCTGGAAAGTGGCAAACGTTCCAAAGCTAAGACATTGGCTATTTCTGGGCTGTTCACAAACTGTGAGGCCAATTCCAGATGAGATCCAGAGAAAGG\t*\tSA:Z:chr10,73660151,-,140S145M,60,0;\tMD:Z:142\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:142\tXS:i:112", true),
                              2, true, null,
                                    new Tuple2<>(new AlignmentInterval(new SimpleInterval("chr10", 73660153, 73660295), 1, 143, TextCigarCodec.decode("143M142S"), false, 60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS, ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL),
                                                 new AlignmentInterval(new SimpleInterval("chr10", 73659956, 73660097), 144, 285, TextCigarCodec.decode("143H142M"), true, 60, 0, 142, ContigAlignmentsModifier.AlnModType.NONE))
        ));

        // invdup one yield to two
        data.add(new ValidLocalData(fromSAMRecordString("asm031213:tig00068\t16\tchrUn_GL000195v1\t49574\t48\t125S270M\t*\t0\t0\tCCAACATGAAGAAACCCCGTCTCTACTAAAAATACAAAATTATCCAGGTGTGGTGTTGTATGCCTGTAATCCTAGCTACTCGGGAGGCCGAGGCAGGAGAATCGCTTGAACCCAGGAGGTGGAGGTTACAGGCATACAACACCACACCTGGATAATTTTGTATTTTTAGTAGAGACGGGGTTTCTTAATGTTGGTCAGGCTGGTCTCATACTCCTGATCTCAGATCATCTGCCCACCTAGGCCTCCCAAAATGCAGGGATTACAGGCATGAGTCACAATGCCCGGCTGTAATTCCCTCTCTTTTATACCTTAGATTTGAATAATTTTTGCTGGATTCTTCAAACATGAAGTATTTTTTGAATTGGAAACTAACTGAATGACTAACTGGTAAGTAG\t*\tSA:Z:chrUn_GL000195v1,49512,+,264S131M,48,1;\tMD:Z:61C21A14G69T70A30\tRG:Z:GATKSVContigAlignments\tNM:i:5\tAS:i:245\tXS:i:216", true),
                                    fromSAMRecordString("asm031213:tig00068\t2048\tchrUn_GL000195v1\t49512\t48\t264H131M\t*\t0\t0\tCTGTAACCTCCACCTCCTGGGTTCAAGCGATTCTCCTGCCTCGGCCTCCCGAGTAGCTAGGATTACAGGCATACAACACCACACCTGGATAATTTTGTATTTTTAGTAGAGACGGGGTTTCTTCATGTTGG\t*\tSA:Z:chrUn_GL000195v1,49574,-,125S270M,48,5;\tMD:Z:20T110\tRG:Z:GATKSVContigAlignments\tNM:i:1\tAS:i:126\tXS:i:62", true),
                              6, true, null,
                                    new Tuple2<>(new AlignmentInterval(new SimpleInterval("chrUn_GL000195v1", 49580, 49843), 1, 264, TextCigarCodec.decode("264M131S"), false, 48, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS, ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL),
                                                 new AlignmentInterval(new SimpleInterval("chrUn_GL000195v1", 49512, 49642), 265, 395, TextCigarCodec.decode("264H131M"), true, 48, 1, 126, ContigAlignmentsModifier.AlnModType.NONE))
        ));

        // invdup two yield to one
        data.add(new ValidLocalData(fromSAMRecordString("asm030182:tig00002\t2048\tchrX\t52729025\t46\t120M249H\t*\t0\t0\tGATAGCATTAGGAGATATACTTAATGAGAAATGACAAGTTAATGGGTGCAGCATACCAACATGGCACATGTATACATATGTAACAAACCTGCACATTGTACACATGTACCCTAAAACTTA\t*\tSA:Z:chrX,52729135,-,261M108S,60,0;\tMD:Z:53C66\tRG:Z:GATKSVContigAlignments\tNM:i:1\tAS:i:115\tXS:i:95", true),
                                    fromSAMRecordString("asm030182:tig00002\t16\tchrX\t52729135\t60\t261M108S\t*\t0\t0\tCTAAAACTTAAAGTACAATAATAATAAAATTTAAAAAAATGTTTTCAAGGATCAATTCTTAACAGTAGAGGAAAATAGGAAAGCGTGTCAGTGGTCCACCAGAAATATTGAGGCATTCCTGGGAGATAGAGTAGATGGGGTCAGACTGATAGAGAAACCCAAGGAGACAAGACCACAGCTCAAATCACTGTAGGCGAGAGATGCTGTTTGTTTTTTGAGACGGAGACTTACTCTGTCGCCCAGGCTGAGTAAGTTTTAGGGTACATGTGTACAATGTGCAGGTTTGTTACATATGTATACATGTGCCATGTTGGTATGCTGCACCCATTAACTTGTCATTTCTCATTAAGTATATCTCCTAATGCTATC\t*\tSA:Z:chrX,52729025,+,120M249S,46,1;\tMD:Z:261\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:261\tXS:i:187", true),
                              12, false, null,
                                    new Tuple2<>(new AlignmentInterval(new SimpleInterval("chrX", 52729025, 52729144), 1, 120, TextCigarCodec.decode("120M249H"), true, 46, 1, 115, ContigAlignmentsModifier.AlnModType.NONE),
                                                 new AlignmentInterval(new SimpleInterval("chrX", 52729135, 52729383), 121, 369, TextCigarCodec.decode("120S249M"), false, 60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS, ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL))
        ));

        return data;
    }

    @DataProvider
    private Object[][] forOverlapYieldingStrategy() {
        final List<Object[]> data = new ArrayList<>(20);

        final AlignmentInterval one = new AlignmentInterval(new SimpleInterval("chr1", 100001, 100100), 1, 100, TextCigarCodec.decode("100M"), false, 60, 0, 100, ContigAlignmentsModifier.AlnModType.NONE);
        final AlignmentInterval two = new AlignmentInterval(new SimpleInterval("chr1", 100041, 100070), 33, 62, TextCigarCodec.decode("30M"), true, 30, 5, 26, ContigAlignmentsModifier.AlnModType.NONE);
        data.add(new Object[]{one, two, true, bareBoneHg38SAMSeqDict, IllegalArgumentException.class});

        data.add(new Object[]{two, one, true, bareBoneHg38SAMSeqDict, IllegalArgumentException.class});

        data.add(new Object[]{fromSAMRecordString("asm004677:tig00000\t2064\tchr1\t202317371\t60\t1393H50M1085H\t*\t0\t0\tGTCTTGCTCTGTTGCCCAGGCTGGAGTGCAGTAGAGCAATCATAGCTCAC\t*\tSA:Z:chr3,15736242,-,1282M1246S,60,0;chr3,15737523,-,1425S377M1D726M,60,4;\tMD:Z:41T8\tRG:Z:GATKSVContigAlignments\tNM:i:1\tAS:i:45\tXS:i:0", true),
                              fromSAMRecordString("asm004677:tig00000\t16\tchr3\t15736242\t60\t1282M1246S\t*\t0\t0\tTTATCTCTTACTGTGCCTTAATTATAAATTAAATTTTATCATCGGTATGTATAGGAAAAAAACACAGTATCTATAGGGTTTGGTACTATCCAATGTTTCAGGCATCCATAGGGGGTCCAGGAACATATCCTCTGTAGATAAGTGGGAACTACTTTGAAAAAGACATGGCAGCCACTAGCTCCCAGCCACAGAATCTTGGGAATGTTACTTTACCTATAAGTTCCTACCCCTGCAACAAAAATGAAAGACTAGACAAGTTGGCTTCAAAGGTTCTTCTGTTACCTTCTCTAAATCTTTGGTGTACACATAAACCCCAATCTTTGCTATGACACCTAGCACAGACAACGTTTGTTGTGTAAGATAACTAAATAGCAATTTTCTTAAATTGTTTTGATGGTTCTGTCACTAAAGTATTATCTTGACTAAATGTTAATAAACTACTAAAAAGCATGTTTTCTAAATTCTGCCTTCCTTTGCTATTTACTTCTGGAAGAACAATAACATATCTCTGTCTTCACATATTTTTCCTGCCACAATAATAGAACATACTTTTCCTGTTGTGTTAAGAGTTGGTATTGTTTTCCTTGGTCACCACAGGTTAACTGTGCACAAGTAGTATCTACTACATACATTTCTAAATTTGAGAAAGTTATAAAAGGAGGCAAAATTAGACAAAAATGAGAAAGATAAATAGTTCTGTATGCCTTTACTATGCAAAAATGCAAGTTCTTTAATAAGTGGGGGGTGGACAGGAGGAGAGAAAAATAATGGTCTAATTGAATGCCACCTACCTCACCATGTCCACTGAAAGCTGCATGATGTAATGCAGTCCTCCCTGCTCGATCAGATACGTTTACATTACTCAGAAGAGGTACCAAAGCTTCAGCACACTTTACAGCTTTATTAGCAGCAGCTATATGTAAAGGGGTTTGCCAATTTTTGTCTCGAGCATTAACATCTGCAGAATGCTTCAAAAGTACCTGAACTGCTTCCTAAAACATATGAAAAGTTATAAAAGACAAATGAGTTAAGAGTTTGAGAAATTATTTCTATATATAGTGTGCGTGTGTGTGTATAAATATGTATCTACATATGAAGAAAATAAAAAAGCTCTCATAGAACTCACTATAAACAAGTAGGAATTTACCCAAGGAAAGAAAATATTTTGAATGTAAAGCGATACTGAGAGTACTCAGAGCCATATAAGATGCATCAAGATCAAACATTCCCTTTCCCTACCCTACCATTAAATGCATAAACATTCCTATCAAAATGTGCAAGAAGAAATACTGACAACTATTATTCAAAAACATTCATTTCTTATATCTTATTTTTCTAGGTAACAAGATACAATTTATACTTTGAATAAATAGTTTTTTGGTTTTGTTTTTTGGTCTTGCTCTGTTGCCCAGGCTGGAGTGCAGTAGAGCAATCATAGCTCACCGTAACTTCAAATTCCTTGGCTTAAGTGATCCTCCCACCTTTGCTTCCTGAGTAGCTAGGACTACAGGTGCATGCCACCACCCCTGGCTAATTTTTTAGTTATTTTGTAGAGACAAGGTCTTGCTATGTTGCCCAGGCTGGTCTCAAACTCCTGGCCTCAAGTGATTCTCCTTCCTTGGCCTCCTGAAGTGTTGGGGTTACAAACATGAGCCAGTCATAGAGCCACACCTGGCTCTTTGAACAATTTTAAGCAATAGATTTTTTACACTGCATATATAAAAATTAAAAACATACTATTTCTCAATGTATTATACATGCTATATTTGACAAAATGAAAAATCACTAGGATCAATTTCATTAAAAAAAAAAAAAGACACAACATAGACAAGGTTCTTTTTGCAGTGCTGCTTAGAGAGAAAGTTAAGGCAATTTAAGAGTCTACTGTCCAAGGGATTTATCTCCCAGAAGCGCATGGAAAACATCACAACACTACCTCTATAAATTGGACTCATGGCAGGATTCCAAGGAATTCAGTATGCCATCAACATTAAGCAATATAATCAGAACTAAACTCAACAAAATTTTTCTTTCAGTGATAATCCTAATTTTTGGTAAATTATCGGGGAACCTGCCCCCAATAATTCAAAGTGAGTCCTTTTCTATTTTCCCTAAGTGTCGGCTGGTCTGAGAAATAAAGGGAAAGAGTACAAAAGAGAGAAATTTTAAAGCTGGGTGTCTGGGGAGACATCACATGCCCAAGCCGCAAAACCAGCAAGTTTTTATTAGTGATTTTCAAAAGGGGAGGGAGAGTACGAATAGGGTATGAGTCACAGAGATCACATGCTTCACAAGGTAATAAAATATTACAAGGCAAATGGAGGCAGGGCGAGATCACAGGACCAGGTGAAATTAACATTGCTAATGAAGTTTTGGGCACACATTGTCATTGATAACATCTTATCAGGAGACAGGGGCCGGGCACAGTGGCGCGTGCCTGTAGTCCCAGCTACTCGGGAGGCTGAGGTGGGAGGATCGCTTGAGCCCAGGAGTTCTGGGCTGTAGTGCGCTATGCCGATCGGGTGTCC\t*\tSA:Z:chr3,15737523,-,1425S377M1D726M,60,4;chr1,202317371,-,1393S50M1085S,60,1;\tMD:Z:1282\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:1282\tXS:i:0", true),
                              true, null, IllegalArgumentException.class
        });

        for (final ValidLocalData validInput : validInputs) {
            data.add(new Object[]{validInput.one, validInput.two, validInput.expectedOneShouldYieldToTwo, bareBoneHg38SAMSeqDict, null});
        }

        return data.toArray(new Object[data.size()][]);
    }

    @Test(groups = "sv", dataProvider = "forOverlapYieldingStrategy")
    @SuppressWarnings("rawtypes")
    public void testYieldOverlapToAlignmentTwo(final AlignmentInterval one, final AlignmentInterval two,
                                               final boolean expectedResults,
                                               final SAMSequenceDictionary refSeqDict,
                                               final Class expectedExceptionClass) {
        try {
            final boolean result = CpxVariantInterpreter.yieldOverlapToAlignmentTwo(one, two, refSeqDict);
            Assert.assertEquals(result, expectedResults);
        } catch (final Exception ex) {
            Assert.assertEquals(ex.getClass(), expectedExceptionClass);
        }
    }


    @DataProvider
    private Object[][] forRemoveOverlap() {
        final List<Object[]> data = new ArrayList<>(20);

        // containment
        final AlignmentInterval one = new AlignmentInterval(new SimpleInterval("chr1", 100001, 100100), 1, 100, TextCigarCodec.decode("100M"), false, 60, 0, 100, ContigAlignmentsModifier.AlnModType.NONE);
        final AlignmentInterval two = new AlignmentInterval(new SimpleInterval("chr1", 100041, 100070), 33, 62, TextCigarCodec.decode("30M"), true, 30, 5, 26, ContigAlignmentsModifier.AlnModType.NONE);
        data.add(new Object[]{one, two, 30, bareBoneHg38SAMSeqDict, false, false, null, IllegalArgumentException.class});

        // not-overlapping
        data.add(new Object[]{fromSAMRecordString("asm004677:tig00000\t2064\tchr3\t15737523\t60\t1425H377M1D726M\t*\t0\t0\tAGAGCAATCATAGCTCACCGTAACTTCAAATTCCTTGGCTTAAGTGATCCTCCCACCTTTGCTTCCTGAGTAGCTAGGACTACAGGTGCATGCCACCACCCCTGGCTAATTTTTTAGTTATTTTGTAGAGACAAGGTCTTGCTATGTTGCCCAGGCTGGTCTCAAACTCCTGGCCTCAAGTGATTCTCCTTCCTTGGCCTCCTGAAGTGTTGGGGTTACAAACATGAGCCAGTCATAGAGCCACACCTGGCTCTTTGAACAATTTTAAGCAATAGATTTTTTACACTGCATATATAAAAATTAAAAACATACTATTTCTCAATGTATTATACATGCTATATTTGACAAAATGAAAAATCACTAGGATCAATTTCATTAAAAAAAAAAAAAGACACAACATAGACAAGGTTCTTTTTGCAGTGCTGCTTAGAGAGAAAGTTAAGGCAATTTAAGAGTCTACTGTCCAAGGGATTTATCTCCCAGAAGCGCATGGAAAACATCACAACACTACCTCTATAAATTGGACTCATGGCAGGATTCCAAGGAATTCAGTATGCCATCAACATTAAGCAATATAATCAGAACTAAACTCAACAAAATTTTTCTTTCAGTGATAATCCTAATTTTTGGTAAATTATCGGGGAACCTGCCCCCAATAATTCAAAGTGAGTCCTTTTCTATTTTCCCTAAGTGTCGGCTGGTCTGAGAAATAAAGGGAAAGAGTACAAAAGAGAGAAATTTTAAAGCTGGGTGTCTGGGGAGACATCACATGCCCAAGCCGCAAAACCAGCAAGTTTTTATTAGTGATTTTCAAAAGGGGAGGGAGAGTACGAATAGGGTATGAGTCACAGAGATCACATGCTTCACAAGGTAATAAAATATTACAAGGCAAATGGAGGCAGGGCGAGATCACAGGACCAGGTGAAATTAACATTGCTAATGAAGTTTTGGGCACACATTGTCATTGATAACATCTTATCAGGAGACAGGGGCCGGGCACAGTGGCGCGTGCCTGTAGTCCCAGCTACTCGGGAGGCTGAGGTGGGAGGATCGCTTGAGCCCAGGAGTTCTGGGCTGTAGTGCGCTATGCCGATCGGGTGTCC\t*\tSA:Z:chr3,15736242,-,1282M1246S,60,0;chr1,202317371,-,1393S50M1085S,60,1;\tMD:Z:164C19C192^A449T276\tRG:Z:GATKSVContigAlignments\tNM:i:4\tAS:i:1071\tXS:i:161", true),
                              fromSAMRecordString("asm004677:tig00000\t16\tchr3\t15736242\t60\t1282M1246S\t*\t0\t0\tTTATCTCTTACTGTGCCTTAATTATAAATTAAATTTTATCATCGGTATGTATAGGAAAAAAACACAGTATCTATAGGGTTTGGTACTATCCAATGTTTCAGGCATCCATAGGGGGTCCAGGAACATATCCTCTGTAGATAAGTGGGAACTACTTTGAAAAAGACATGGCAGCCACTAGCTCCCAGCCACAGAATCTTGGGAATGTTACTTTACCTATAAGTTCCTACCCCTGCAACAAAAATGAAAGACTAGACAAGTTGGCTTCAAAGGTTCTTCTGTTACCTTCTCTAAATCTTTGGTGTACACATAAACCCCAATCTTTGCTATGACACCTAGCACAGACAACGTTTGTTGTGTAAGATAACTAAATAGCAATTTTCTTAAATTGTTTTGATGGTTCTGTCACTAAAGTATTATCTTGACTAAATGTTAATAAACTACTAAAAAGCATGTTTTCTAAATTCTGCCTTCCTTTGCTATTTACTTCTGGAAGAACAATAACATATCTCTGTCTTCACATATTTTTCCTGCCACAATAATAGAACATACTTTTCCTGTTGTGTTAAGAGTTGGTATTGTTTTCCTTGGTCACCACAGGTTAACTGTGCACAAGTAGTATCTACTACATACATTTCTAAATTTGAGAAAGTTATAAAAGGAGGCAAAATTAGACAAAAATGAGAAAGATAAATAGTTCTGTATGCCTTTACTATGCAAAAATGCAAGTTCTTTAATAAGTGGGGGGTGGACAGGAGGAGAGAAAAATAATGGTCTAATTGAATGCCACCTACCTCACCATGTCCACTGAAAGCTGCATGATGTAATGCAGTCCTCCCTGCTCGATCAGATACGTTTACATTACTCAGAAGAGGTACCAAAGCTTCAGCACACTTTACAGCTTTATTAGCAGCAGCTATATGTAAAGGGGTTTGCCAATTTTTGTCTCGAGCATTAACATCTGCAGAATGCTTCAAAAGTACCTGAACTGCTTCCTAAAACATATGAAAAGTTATAAAAGACAAATGAGTTAAGAGTTTGAGAAATTATTTCTATATATAGTGTGCGTGTGTGTGTATAAATATGTATCTACATATGAAGAAAATAAAAAAGCTCTCATAGAACTCACTATAAACAAGTAGGAATTTACCCAAGGAAAGAAAATATTTTGAATGTAAAGCGATACTGAGAGTACTCAGAGCCATATAAGATGCATCAAGATCAAACATTCCCTTTCCCTACCCTACCATTAAATGCATAAACATTCCTATCAAAATGTGCAAGAAGAAATACTGACAACTATTATTCAAAAACATTCATTTCTTATATCTTATTTTTCTAGGTAACAAGATACAATTTATACTTTGAATAAATAGTTTTTTGGTTTTGTTTTTTGGTCTTGCTCTGTTGCCCAGGCTGGAGTGCAGTAGAGCAATCATAGCTCACCGTAACTTCAAATTCCTTGGCTTAAGTGATCCTCCCACCTTTGCTTCCTGAGTAGCTAGGACTACAGGTGCATGCCACCACCCCTGGCTAATTTTTTAGTTATTTTGTAGAGACAAGGTCTTGCTATGTTGCCCAGGCTGGTCTCAAACTCCTGGCCTCAAGTGATTCTCCTTCCTTGGCCTCCTGAAGTGTTGGGGTTACAAACATGAGCCAGTCATAGAGCCACACCTGGCTCTTTGAACAATTTTAAGCAATAGATTTTTTACACTGCATATATAAAAATTAAAAACATACTATTTCTCAATGTATTATACATGCTATATTTGACAAAATGAAAAATCACTAGGATCAATTTCATTAAAAAAAAAAAAAGACACAACATAGACAAGGTTCTTTTTGCAGTGCTGCTTAGAGAGAAAGTTAAGGCAATTTAAGAGTCTACTGTCCAAGGGATTTATCTCCCAGAAGCGCATGGAAAACATCACAACACTACCTCTATAAATTGGACTCATGGCAGGATTCCAAGGAATTCAGTATGCCATCAACATTAAGCAATATAATCAGAACTAAACTCAACAAAATTTTTCTTTCAGTGATAATCCTAATTTTTGGTAAATTATCGGGGAACCTGCCCCCAATAATTCAAAGTGAGTCCTTTTCTATTTTCCCTAAGTGTCGGCTGGTCTGAGAAATAAAGGGAAAGAGTACAAAAGAGAGAAATTTTAAAGCTGGGTGTCTGGGGAGACATCACATGCCCAAGCCGCAAAACCAGCAAGTTTTTATTAGTGATTTTCAAAAGGGGAGGGAGAGTACGAATAGGGTATGAGTCACAGAGATCACATGCTTCACAAGGTAATAAAATATTACAAGGCAAATGGAGGCAGGGCGAGATCACAGGACCAGGTGAAATTAACATTGCTAATGAAGTTTTGGGCACACATTGTCATTGATAACATCTTATCAGGAGACAGGGGCCGGGCACAGTGGCGCGTGCCTGTAGTCCCAGCTACTCGGGAGGCTGAGGTGGGAGGATCGCTTGAGCCCAGGAGTTCTGGGCTGTAGTGCGCTATGCCGATCGGGTGTCC\t*\tSA:Z:chr3,15737523,-,1425S377M1D726M,60,4;chr1,202317371,-,1393H50M1085H,60,1;\tMD:Z:1282\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:1282\tXS:i:0", true),
                              0, bareBoneHg38SAMSeqDict, false, false, null, IllegalArgumentException.class
        });

        // all cases for valid inputs in testYieldOverlapToAlignmentTwo
        data.add(new Object[]{validInputs.get(1).one, validInputs.get(1).two, validInputs.get(1).overlapOnRead, bareBoneHg38SAMSeqDict, false, false, validInputs.get(1).expectedDeOverlapedAlignments, null});
        data.add(new Object[]{validInputs.get(2).one, validInputs.get(2).two, validInputs.get(2).overlapOnRead, bareBoneHg38SAMSeqDict, false, false, validInputs.get(2).expectedDeOverlapedAlignments, null});
        data.add(new Object[]{validInputs.get(3).one, validInputs.get(3).two, validInputs.get(3).overlapOnRead, bareBoneHg38SAMSeqDict, false, false, validInputs.get(3).expectedDeOverlapedAlignments, null});
        data.add(new Object[]{validInputs.get(4).one, validInputs.get(4).two, validInputs.get(4).overlapOnRead, bareBoneHg38SAMSeqDict, false, false, validInputs.get(4).expectedDeOverlapedAlignments, null});
        data.add(new Object[]{validInputs.get(5).one, validInputs.get(5).two, validInputs.get(5).overlapOnRead, bareBoneHg38SAMSeqDict, false, false, validInputs.get(5).expectedDeOverlapedAlignments, null});
        data.add(new Object[]{validInputs.get(6).one, validInputs.get(6).two, validInputs.get(6).overlapOnRead, bareBoneHg38SAMSeqDict, false, false, validInputs.get(6).expectedDeOverlapedAlignments, null});
        data.add(new Object[]{validInputs.get(7).one, validInputs.get(7).two, validInputs.get(7).overlapOnRead, bareBoneHg38SAMSeqDict, false, false, validInputs.get(7).expectedDeOverlapedAlignments, null});
        data.add(new Object[]{validInputs.get(8).one, validInputs.get(8).two, validInputs.get(8).overlapOnRead, bareBoneHg38SAMSeqDict, false, false, validInputs.get(8).expectedDeOverlapedAlignments, null});

        data.add(new Object[]{validInputs.get(0).one, validInputs.get(0).two, validInputs.get(0).overlapOnRead, bareBoneHg38SAMSeqDict, false, true, validInputs.get(0).expectedDeOverlapedAlignments, null});

        return data.toArray(new Object[data.size()][]);
    }

    @Test(groups = "sv", dataProvider = "forRemoveOverlap")
    @SuppressWarnings("rawtypes")
    public void testRemoveOverlap(final AlignmentInterval one, final AlignmentInterval two,
                                  final int overlapOnRead,
                                  final SAMSequenceDictionary dictionary,
                                  final boolean firstIsAlignmentHead,
                                  final boolean secondIsAlignmentTail,
                                  final Tuple2<AlignmentInterval, AlignmentInterval> expectedResults,
                                  final Class expectedExceptionClass) {
        try {
            final Tuple2<AlignmentInterval, AlignmentInterval> result = CpxVariantInterpreter.removeOverlap(one, two, overlapOnRead, dictionary, firstIsAlignmentHead, secondIsAlignmentTail);
            Assert.assertEquals(result, expectedResults);
        } catch (final Exception ex) {
            Assert.assertEquals(ex.getClass(), expectedExceptionClass);
        }
    }

    // =================================================================================================================

    // TODO: 6/25/18 add more test cases here: the 1bp alignment block case
    @DataProvider
    private Object[][] forTestDeOverlapMultipleAlignments() {
        final List<Object[]> data = new ArrayList<>(20);

        final AlignedContig contigOne = fromPrimarySAMRecordString("asm004677:tig00000\t16\tchr3\t15736242\t60\t1282M1246S\t*\t0\t0\tTTATCTCTTACTGTGCCTTAATTATAAATTAAATTTTATCATCGGTATGTATAGGAAAAAAACACAGTATCTATAGGGTTTGGTACTATCCAATGTTTCAGGCATCCATAGGGGGTCCAGGAACATATCCTCTGTAGATAAGTGGGAACTACTTTGAAAAAGACATGGCAGCCACTAGCTCCCAGCCACAGAATCTTGGGAATGTTACTTTACCTATAAGTTCCTACCCCTGCAACAAAAATGAAAGACTAGACAAGTTGGCTTCAAAGGTTCTTCTGTTACCTTCTCTAAATCTTTGGTGTACACATAAACCCCAATCTTTGCTATGACACCTAGCACAGACAACGTTTGTTGTGTAAGATAACTAAATAGCAATTTTCTTAAATTGTTTTGATGGTTCTGTCACTAAAGTATTATCTTGACTAAATGTTAATAAACTACTAAAAAGCATGTTTTCTAAATTCTGCCTTCCTTTGCTATTTACTTCTGGAAGAACAATAACATATCTCTGTCTTCACATATTTTTCCTGCCACAATAATAGAACATACTTTTCCTGTTGTGTTAAGAGTTGGTATTGTTTTCCTTGGTCACCACAGGTTAACTGTGCACAAGTAGTATCTACTACATACATTTCTAAATTTGAGAAAGTTATAAAAGGAGGCAAAATTAGACAAAAATGAGAAAGATAAATAGTTCTGTATGCCTTTACTATGCAAAAATGCAAGTTCTTTAATAAGTGGGGGGTGGACAGGAGGAGAGAAAAATAATGGTCTAATTGAATGCCACCTACCTCACCATGTCCACTGAAAGCTGCATGATGTAATGCAGTCCTCCCTGCTCGATCAGATACGTTTACATTACTCAGAAGAGGTACCAAAGCTTCAGCACACTTTACAGCTTTATTAGCAGCAGCTATATGTAAAGGGGTTTGCCAATTTTTGTCTCGAGCATTAACATCTGCAGAATGCTTCAAAAGTACCTGAACTGCTTCCTAAAACATATGAAAAGTTATAAAAGACAAATGAGTTAAGAGTTTGAGAAATTATTTCTATATATAGTGTGCGTGTGTGTGTATAAATATGTATCTACATATGAAGAAAATAAAAAAGCTCTCATAGAACTCACTATAAACAAGTAGGAATTTACCCAAGGAAAGAAAATATTTTGAATGTAAAGCGATACTGAGAGTACTCAGAGCCATATAAGATGCATCAAGATCAAACATTCCCTTTCCCTACCCTACCATTAAATGCATAAACATTCCTATCAAAATGTGCAAGAAGAAATACTGACAACTATTATTCAAAAACATTCATTTCTTATATCTTATTTTTCTAGGTAACAAGATACAATTTATACTTTGAATAAATAGTTTTTTGGTTTTGTTTTTTGGTCTTGCTCTGTTGCCCAGGCTGGAGTGCAGTAGAGCAATCATAGCTCACCGTAACTTCAAATTCCTTGGCTTAAGTGATCCTCCCACCTTTGCTTCCTGAGTAGCTAGGACTACAGGTGCATGCCACCACCCCTGGCTAATTTTTTAGTTATTTTGTAGAGACAAGGTCTTGCTATGTTGCCCAGGCTGGTCTCAAACTCCTGGCCTCAAGTGATTCTCCTTCCTTGGCCTCCTGAAGTGTTGGGGTTACAAACATGAGCCAGTCATAGAGCCACACCTGGCTCTTTGAACAATTTTAAGCAATAGATTTTTTACACTGCATATATAAAAATTAAAAACATACTATTTCTCAATGTATTATACATGCTATATTTGACAAAATGAAAAATCACTAGGATCAATTTCATTAAAAAAAAAAAAAGACACAACATAGACAAGGTTCTTTTTGCAGTGCTGCTTAGAGAGAAAGTTAAGGCAATTTAAGAGTCTACTGTCCAAGGGATTTATCTCCCAGAAGCGCATGGAAAACATCACAACACTACCTCTATAAATTGGACTCATGGCAGGATTCCAAGGAATTCAGTATGCCATCAACATTAAGCAATATAATCAGAACTAAACTCAACAAAATTTTTCTTTCAGTGATAATCCTAATTTTTGGTAAATTATCGGGGAACCTGCCCCCAATAATTCAAAGTGAGTCCTTTTCTATTTTCCCTAAGTGTCGGCTGGTCTGAGAAATAAAGGGAAAGAGTACAAAAGAGAGAAATTTTAAAGCTGGGTGTCTGGGGAGACATCACATGCCCAAGCCGCAAAACCAGCAAGTTTTTATTAGTGATTTTCAAAAGGGGAGGGAGAGTACGAATAGGGTATGAGTCACAGAGATCACATGCTTCACAAGGTAATAAAATATTACAAGGCAAATGGAGGCAGGGCGAGATCACAGGACCAGGTGAAATTAACATTGCTAATGAAGTTTTGGGCACACATTGTCATTGATAACATCTTATCAGGAGACAGGGGCCGGGCACAGTGGCGCGTGCCTGTAGTCCCAGCTACTCGGGAGGCTGAGGTGGGAGGATCGCTTGAGCCCAGGAGTTCTGGGCTGTAGTGCGCTATGCCGATCGGGTGTCC\t*\tSA:Z:chr3,15737523,-,1425H377M1D726M,60,4,1071;chr1,202317371,-,1393H50M1085H,60,1,45;\tMD:Z:1282\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:1282\tXS:i:0",
                true);
        final AlignmentInterval middleForContigOne = new AlignmentInterval(
                new SimpleInterval("chr1", 202317371, 202317402),
                1104, 1135,
                TextCigarCodec.decode("1085H18S32M1393H"), false,
                60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS,
                ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL);
        data.add(new Object[]{contigOne.getAlignments(),
                Arrays.asList(fromSAMRecordString("asm004677:tig00000\t2064\tchr3\t15737523\t60\t1425H377M1D726M\t*\t0\t0\tAGAGCAATCATAGCTCACCGTAACTTCAAATTCCTTGGCTTAAGTGATCCTCCCACCTTTGCTTCCTGAGTAGCTAGGACTACAGGTGCATGCCACCACCCCTGGCTAATTTTTTAGTTATTTTGTAGAGACAAGGTCTTGCTATGTTGCCCAGGCTGGTCTCAAACTCCTGGCCTCAAGTGATTCTCCTTCCTTGGCCTCCTGAAGTGTTGGGGTTACAAACATGAGCCAGTCATAGAGCCACACCTGGCTCTTTGAACAATTTTAAGCAATAGATTTTTTACACTGCATATATAAAAATTAAAAACATACTATTTCTCAATGTATTATACATGCTATATTTGACAAAATGAAAAATCACTAGGATCAATTTCATTAAAAAAAAAAAAAGACACAACATAGACAAGGTTCTTTTTGCAGTGCTGCTTAGAGAGAAAGTTAAGGCAATTTAAGAGTCTACTGTCCAAGGGATTTATCTCCCAGAAGCGCATGGAAAACATCACAACACTACCTCTATAAATTGGACTCATGGCAGGATTCCAAGGAATTCAGTATGCCATCAACATTAAGCAATATAATCAGAACTAAACTCAACAAAATTTTTCTTTCAGTGATAATCCTAATTTTTGGTAAATTATCGGGGAACCTGCCCCCAATAATTCAAAGTGAGTCCTTTTCTATTTTCCCTAAGTGTCGGCTGGTCTGAGAAATAAAGGGAAAGAGTACAAAAGAGAGAAATTTTAAAGCTGGGTGTCTGGGGAGACATCACATGCCCAAGCCGCAAAACCAGCAAGTTTTTATTAGTGATTTTCAAAAGGGGAGGGAGAGTACGAATAGGGTATGAGTCACAGAGATCACATGCTTCACAAGGTAATAAAATATTACAAGGCAAATGGAGGCAGGGCGAGATCACAGGACCAGGTGAAATTAACATTGCTAATGAAGTTTTGGGCACACATTGTCATTGATAACATCTTATCAGGAGACAGGGGCCGGGCACAGTGGCGCGTGCCTGTAGTCCCAGCTACTCGGGAGGCTGAGGTGGGAGGATCGCTTGAGCCCAGGAGTTCTGGGCTGTAGTGCGCTATGCCGATCGGGTGTCC\t*\tSA:Z:chr3,15736242,-,1282M1246S,60,0;chr1,202317371,-,1393S50M1085S,60,1;\tMD:Z:164C19C192^A449T276\tRG:Z:GATKSVContigAlignments\tNM:i:4\tAS:i:1071\tXS:i:161", true),
                              middleForContigOne,
                              fromSAMRecordString("asm004677:tig00000\t16\tchr3\t15736242\t60\t1282M1246S\t*\t0\t0\tTTATCTCTTACTGTGCCTTAATTATAAATTAAATTTTATCATCGGTATGTATAGGAAAAAAACACAGTATCTATAGGGTTTGGTACTATCCAATGTTTCAGGCATCCATAGGGGGTCCAGGAACATATCCTCTGTAGATAAGTGGGAACTACTTTGAAAAAGACATGGCAGCCACTAGCTCCCAGCCACAGAATCTTGGGAATGTTACTTTACCTATAAGTTCCTACCCCTGCAACAAAAATGAAAGACTAGACAAGTTGGCTTCAAAGGTTCTTCTGTTACCTTCTCTAAATCTTTGGTGTACACATAAACCCCAATCTTTGCTATGACACCTAGCACAGACAACGTTTGTTGTGTAAGATAACTAAATAGCAATTTTCTTAAATTGTTTTGATGGTTCTGTCACTAAAGTATTATCTTGACTAAATGTTAATAAACTACTAAAAAGCATGTTTTCTAAATTCTGCCTTCCTTTGCTATTTACTTCTGGAAGAACAATAACATATCTCTGTCTTCACATATTTTTCCTGCCACAATAATAGAACATACTTTTCCTGTTGTGTTAAGAGTTGGTATTGTTTTCCTTGGTCACCACAGGTTAACTGTGCACAAGTAGTATCTACTACATACATTTCTAAATTTGAGAAAGTTATAAAAGGAGGCAAAATTAGACAAAAATGAGAAAGATAAATAGTTCTGTATGCCTTTACTATGCAAAAATGCAAGTTCTTTAATAAGTGGGGGGTGGACAGGAGGAGAGAAAAATAATGGTCTAATTGAATGCCACCTACCTCACCATGTCCACTGAAAGCTGCATGATGTAATGCAGTCCTCCCTGCTCGATCAGATACGTTTACATTACTCAGAAGAGGTACCAAAGCTTCAGCACACTTTACAGCTTTATTAGCAGCAGCTATATGTAAAGGGGTTTGCCAATTTTTGTCTCGAGCATTAACATCTGCAGAATGCTTCAAAAGTACCTGAACTGCTTCCTAAAACATATGAAAAGTTATAAAAGACAAATGAGTTAAGAGTTTGAGAAATTATTTCTATATATAGTGTGCGTGTGTGTGTATAAATATGTATCTACATATGAAGAAAATAAAAAAGCTCTCATAGAACTCACTATAAACAAGTAGGAATTTACCCAAGGAAAGAAAATATTTTGAATGTAAAGCGATACTGAGAGTACTCAGAGCCATATAAGATGCATCAAGATCAAACATTCCCTTTCCCTACCCTACCATTAAATGCATAAACATTCCTATCAAAATGTGCAAGAAGAAATACTGACAACTATTATTCAAAAACATTCATTTCTTATATCTTATTTTTCTAGGTAACAAGATACAATTTATACTTTGAATAAATAGTTTTTTGGTTTTGTTTTTTGGTCTTGCTCTGTTGCCCAGGCTGGAGTGCAGTAGAGCAATCATAGCTCACCGTAACTTCAAATTCCTTGGCTTAAGTGATCCTCCCACCTTTGCTTCCTGAGTAGCTAGGACTACAGGTGCATGCCACCACCCCTGGCTAATTTTTTAGTTATTTTGTAGAGACAAGGTCTTGCTATGTTGCCCAGGCTGGTCTCAAACTCCTGGCCTCAAGTGATTCTCCTTCCTTGGCCTCCTGAAGTGTTGGGGTTACAAACATGAGCCAGTCATAGAGCCACACCTGGCTCTTTGAACAATTTTAAGCAATAGATTTTTTACACTGCATATATAAAAATTAAAAACATACTATTTCTCAATGTATTATACATGCTATATTTGACAAAATGAAAAATCACTAGGATCAATTTCATTAAAAAAAAAAAAAGACACAACATAGACAAGGTTCTTTTTGCAGTGCTGCTTAGAGAGAAAGTTAAGGCAATTTAAGAGTCTACTGTCCAAGGGATTTATCTCCCAGAAGCGCATGGAAAACATCACAACACTACCTCTATAAATTGGACTCATGGCAGGATTCCAAGGAATTCAGTATGCCATCAACATTAAGCAATATAATCAGAACTAAACTCAACAAAATTTTTCTTTCAGTGATAATCCTAATTTTTGGTAAATTATCGGGGAACCTGCCCCCAATAATTCAAAGTGAGTCCTTTTCTATTTTCCCTAAGTGTCGGCTGGTCTGAGAAATAAAGGGAAAGAGTACAAAAGAGAGAAATTTTAAAGCTGGGTGTCTGGGGAGACATCACATGCCCAAGCCGCAAAACCAGCAAGTTTTTATTAGTGATTTTCAAAAGGGGAGGGAGAGTACGAATAGGGTATGAGTCACAGAGATCACATGCTTCACAAGGTAATAAAATATTACAAGGCAAATGGAGGCAGGGCGAGATCACAGGACCAGGTGAAATTAACATTGCTAATGAAGTTTTGGGCACACATTGTCATTGATAACATCTTATCAGGAGACAGGGGCCGGGCACAGTGGCGCGTGCCTGTAGTCCCAGCTACTCGGGAGGCTGAGGTGGGAGGATCGCTTGAGCCCAGGAGTTCTGGGCTGTAGTGCGCTATGCCGATCGGGTGTCC\t*\tSA:Z:chr3,15737523,-,1425S377M1D726M,60,4;chr1,202317371,-,1393H50M1085H,60,1;\tMD:Z:1282\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:1282\tXS:i:0", true)
                )
        });


        final AlignedContig contigTwo = fromPrimarySAMRecordString("asm004901:tig00000\t0\tchr3\t44699487\t60\t786S1319M692S\t*\t0\t0\tGGTGGCGGGCGCCTGTAGTCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATGGCATGAACCCGGGAAGCGGAGCTTGCAGTGAGCCGAGATTGCGCCACTGCAGTCCGCAGTCTGGCCTGGGCAACAGAGCGAGACTCCGTCTCAAAAAAAAAAAAAAAAAAGAAAATGGCTTTGGAAACTGGATTTTTGTTGTAGACTTGATAATGTTTCCCAATGAATTACAAGGCAAAACAGTTCTTATATGTGAAACTTATACTGTAGTAAAGTTATTCTGACAACTGACATAGTCTGAATCACAAGCAAAATCAAGCTGCTCTATATGCTTTTTTTGGCTATTGAAAGTTAAAAAAAGAAGTGAGATCTTCACTCCTATCCAAACTGGCTGCAGGCATGTTTTTTGAACTCAAATCACAGTTCCAGAAGTAGTTTTCAGATCACAACTTGATGCAAGTGCAAAGGAAATAAGAAAATTTCCTTCCTCCCTCCCTCCCTTCCTCCTTCCCTTCCTTCCTTCCTTCCTTCCTTCCTTCCTTCCTTCCTTCCTTCCTCCCTCCCTCCCTTCCTTCCTTCTTTCCTTCTTTCCTCTCTATCTCTTTTTCTTTCTTGCTTTGTGGAGACCAGGTCTTGCCATTTTGCCTAGGCTGGTCTTGAACTCCTAGGCTTAAGTGATTCTCCCTCCTCAGCCTCCCAAAGAGAAATTTTCATATTTACAAATCCATTTAAGAGGCAATTGAAAAAACATTTAAATTTTAATTTTAAAAAAGAGGCAGTGGAGTGGCCGGGTGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAAGCCAAGGGGGGCAGATCACGAGGTCAGGAGATCGAGACCATCCTGGCTAACATGGTGAAACCCCGTCTCTACTAAAAAAATACAAAAAAATTAGCCAGGTGTGGTGGTGGATGCCTGCAGTCCCAGCTACTCTGGAGGCTGAGGCAGGAGAATGGCGTGAACCCGGGAGGCAGAGCTTGCAATGAGCTGAGACTGAGCCACTGCACTACAGCCTGGGCAACAGAGCGAGACTGCATCTCAACAACAACAACAAAAAAACGCAGTGGAAAAGTTTCCACAAACCTTTGTTGGGGAAATATAATTAAAAACAAATCCTTCTTCCAACCCAGAAATTCTCTCTACAAAGGTAGCAGGGAAAGAATACACTATTAAAGAAGCATTAAACTAGAATGTAACACATATCACAGGCAACCTACAAAGAGATTGAAAAGGCAGAAAGAAATCTCGCCTCCTTATATAGCCGAACAGATACAACCCATTACATACATGCTTTCAAGATAAACAATAACTAGTCTTCAAATAAGAGGTCTTGGCAGCACCTTTTGTCACATGGTTTTTCCCAACTTTATTGTGGTAATTGGAGTGACCATCTATGTTAGCTAATTGGCTTTATCCAGAGGAAAATCTTCTCAACTTTTTATGGCAGAGGTAGTTTTGCAACTTCAAGCAGGGCACCCACCGAAGCTAAGCTCTAATTTTTGCTATTCAAAGAGATGGCTTTCAGGTCCTCGAGAAAAACATTCCTTGGTCATGGAGCTGAGAAAAGGCCAGTTGGCAAAAGTCCTGCCTAGTCTTCAAAAGCCTATATATACATATGTATTTCAAAGAAAAGAGAAAATACTTACAAGTTTTCTAAGGTAAATGTCCTGAGAAAAAGGAGGGGAGGGAAATCTCTTCTCCTGTTTTCACCAGAGTAAATTGAACCTCTTATTTTTAATTTGCATTTGCCCTTATATTTTCTATGTGAAAACACATTTTCTTTTTTCTTCTCTTTTCTTTTCTTTTTTTTTTTTGACGGAGTCTCCCTCAGCCACCCAGGCTGGAGTGCAGTGGCATGATCTTGGCTCACCACAACCACCATCTCCTGGGTTCAAGTGATTCTCCCATCTCAGCCTCCCGAGTAGCTGGGATTACAGGCACCCGCCATCATGCCCGGCTAATTTTTGTATTTTAGTAGAGACAGGGTTTCACCTTGTTGGCCAGGCTGGTCTTGAACTCCTGACCTCAGGTGATCCATCCACCTTGGCCTCCCAAAGTGCTGGGATTACAGGTTTGAGCCACCGTGCCCAGCCAAAACACATTTTCTGGTTTGTTTGTTTTTGTAATTTAAGACCAAATAATTTATTTTGGGAAATTTATTGTGAATAGACATTAAAAATAGGTTCATTTGTGCAAAGTAATCTAAACAATGAATGTTTGTGCATATATATATATATATATATATACTGATATATATATACGCACATATACACATACATAACACAATTCTGTATGGGAAATTCATTAAACAACGAGTAGAGTCAACAGTTTGAGTCTCTCAATAACTTAGTAAAAAGCAATATTGATCTTTATAAAAATAATTTTAAAACTTTTTTCTGTTTGTGAAAAATAAAATATCAATTTGAAAATTACTGTCAGACCATGAAGGCAAATAAGAAGTAATATAATCTATCTTCATTTATAGATGAGGAAGAAAGTGACTCCAGAAAAGTTAAATAAAACTTTCTTAAAATTATGTAGGCAGTTATAGTGGCAGAGCTGGGTTATTAATCTGTTACTCCTCACTTACAGTTCAGTGGTTTGGTTTTTTTGTTTGTTTGTTTTGTTTATTCTGCTCCTACTGTTTCCATCTCAGCCTTAACATTTCCTTTTATTCTTCATTTGAGCTAAGCATTCTTTTCTTCTAAAGAAGACCATCGACTTTATTTGAATCATAAGTCACACACACAAACACACACACACACACACACACACA\t*\tSA:Z:chr3,44700691,-,1898H58M2D292M12D387M1I161M,60,26,780;chr3,44698789,-,530M6D217M2I58M1990H,60,19,710,;\tMD:Z:10A0A1295C0G10\tRG:Z:GATKSVContigAlignments\tNM:i:4\tAS:i:1299\tXS:i:0", true);
        final AlignmentInterval middleForContigTwo = new AlignmentInterval(
                new SimpleInterval("chr3", 44699600, 44700690),
                900, 1990,
                TextCigarCodec.decode("899S1091M807S"), true,
                60, AlignmentInterval.NO_NM, AlignmentInterval.NO_AS,
                ContigAlignmentsModifier.AlnModType.UNDERGONE_OVERLAP_REMOVAL);
        data.add(new Object[]{contigTwo.getAlignments(),
                Arrays.asList(fromSAMRecordString("asm004901:tig00000\t2064\tchr3\t44700691\t60\t1898H58M2D292M12D387M1I161M\t*\t0\t0\tTTTTAGTAGAGACGGGGTTTCACCATGTTAGCCAGGATGGTCTCGATCTCCTGACCTCGTGATCTGCCCCCCTTGGCTTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCACCCGGCCACTCCACTGCCTCTTTTTTAAAATTAAAATTTAAATGTTTTTTCAATTGCCTCTTAAATGGATTTGTAAATATGAAAATTTCTCTTTGGGAGGCTGAGGAGGGAGAATCACTTAAGCCTAGGAGTTCAAGACCAGCCTAGGCAAAATGGCAAGACCTGGTCTCCACAAAGCAAGAAAGAAAAAGAGATAGAGAGGAAAGAAGGAAAGAAGGAAGGAAGGGAGGGAGGGAGGAAGGAAGGAAGGAAGGAAGGAAGGAAGGAAGGAAGGAAGGAAGGGAAGGAGGAAGGGAGGGAGGGAGGAAGGAAATTTTCTTATTTCCTTTGCACTTGCATCAAGTTGTGATCTGAAAACTACTTCTGGAACTGTGATTTGAGTTCAAAAAACATGCCTGCAGCCAGTTTGGATAGGAGTGAAGATCTCACTTCTTTTTTTAACTTTCAATAGCCAAAAAAAGCATATAGAGCAGCTTGATTTTGCTTGTGATTCAGACTATGTCAGTTGTCAGAATAACTTTACTACAGTATAAGTTTCACATATAAGAACTGTTTTGCCTTGTAATTCATTGGGAAACATTATCAAGTCTACAACAAAAATCCAGTTTCCAAAGCCATTTTCTTTTTTTTTTTTTTTTTTGAGACGGAGTCTCGCTCTGTTGCCCAGGCCAGACTGCGGACTGCAGTGGCGCAATCTCGGCTCACTGCAAGCTCCGCTTCCCGGGTTCATGCCATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGACTACAGGCGCCCGCCACC\t*\tSA:Z:chr3,44699487,+,786S1319M692S,60,4;chr3,44698789,-,530M6D217M2I58M1990S,60,19;\tMD:Z:13A10T4G6C6T2A11^AG6C0A0T2A7C272^AGGAAGGAAGGA548\tRG:Z:GATKSVContigAlignments\tNM:i:26\tAS:i:780\tXS:i:0", true),
                              middleForContigTwo,
                              fromSAMRecordString("asm004901:tig00000\t2064\tchr3\t44698789\t60\t530M6D217M2I58M1990H\t*\t0\t0\tTGTGTGTGTGTGTGTGTGTGTGTGTTTGTGTGTGTGACTTATGATTCAAATAAAGTCGATGGTCTTCTTTAGAAGAAAAGAATGCTTAGCTCAAATGAAGAATAAAAGGAAATGTTAAGGCTGAGATGGAAACAGTAGGAGCAGAATAAACAAAACAAACAAACAAAAAAACCAAACCACTGAACTGTAAGTGAGGAGTAACAGATTAATAACCCAGCTCTGCCACTATAACTGCCTACATAATTTTAAGAAAGTTTTATTTAACTTTTCTGGAGTCACTTTCTTCCTCATCTATAAATGAAGATAGATTATATTACTTCTTATTTGCCTTCATGGTCTGACAGTAATTTTCAAATTGATATTTTATTTTTCACAAACAGAAAAAAGTTTTAAAATTATTTTTATAAAGATCAATATTGCTTTTTACTAAGTTATTGAGAGACTCAAACTGTTGACTCTACTCGTTGTTTAATGAATTTCCCATACAGAATTGTGTTATGTATGTGTATATGTGCGTATATATATATCAGTATATATATATATATATATATATGCACAAACATTCATTGTTTAGATTACTTTGCACAAATGAACCTATTTTTAATGTCTATTCACAATAAATTTCCCAAAATAAATTATTTGGTCTTAAATTACAAAAACAAACAAACCAGAAAATGTGTTTTGGCTGGGCACGGTGGCTCAAACCTGTAATCCCAGCACTTTGGGAGGCCAAGGTGGATGGATCACCTGAGGTCAGGAGTTCAAGACCAGCCTGGCCAACAAGGTGAAACCCTGTCTCTACTAAAA\t*\tSA:Z:chr3,44699487,+,786S1319M692S,60,4;chr3,44700691,-,1898S58M2D292M12D387M1I161M,60,26;\tMD:Z:530^TATATA197A7G2G0C0A17A2G6T6T4T10C13\tRG:Z:GATKSVContigAlignments\tNM:i:19\tAS:i:710\tXS:i:0", true)
                )
        });

        final AlignmentInterval gappedAln = fromSAMRecordString("asm029245:tig00000\t0\tchr21\t42282466\t60\t1257M61D114M1I60M1D63M1I28M467S\t*\t0\t0\tCCTGTATTCAGCGGTTCTTCCAGGTGACCCTGACATCCTGATGTAGCCTCAGAGGGGGTGAGTTGAGCTCACCCGGCGGTTCCTCCTTCCATCTGGGACCACTGGGCAGAAGAGCTGACTTATGCCCCCTCTCTCACTCACTCTGTGCTCAGGCCTGCAAGGCTTGTGTTGACCCTGGGGGTATGGCTTTGGGGGAAACGTCCTTTCACGATGCATATCTCTTCCATGACACCAAGTTCCCCGTGGCTCAGCCACTCTGAGGGCCAAGGTCACGGGACGACCTGGGAAACGGTGTGTCTTCAGGTGTGTTCTGGAAACGCCCTGCAGTTTAGCACAGCAGAGGCTCGGAGATGCCTGCAGGACAGGATCCTGCCTCGGTTGCTCACCAGCTCTCTATACCCACGGGCGCTCTGACCCCGCCTGCAGGACAGGATCCTGCCTCAGTTGCTCACCAGCTCTCTATACCCACGGGCGCTCTGACCCCTTTCCTGGGTGATGCCCTTTATGTTTGGGGCTCCCTGCGGAATCACTACCCTGGAGTCCTGGATCTGGTGCCCCCAGCCGCAGGTTGAGCTCGCCTGACTCCTGCATGTGTCCTGTCCAGTTGTCCCAGGCAGGATGGGTGGCCAGGAACCAGGCTTCTCCTGAAATGACTTCAGCCAGACTTTACGTTGTCTCATTTCTGCCACTCACTCACCTCTCCAAAGTCCAGCGAGATTTGACAGTAGTGTGACAGCAGCCTTCTGAGGGGGGGATGGCGGGGCTCACTTGTTTCCTTCTCTTGGGCCTGCACAGTAACAGCCCACAGTGTCTATAAGATACTTCAGGAAAAGAGACCACAATGAACCCTTGAATAGCATCTTGCAGGCTGAATGCCCTGAGATGGGTGGGCTCCGGGGGACTGCCCAACACACACTGTCCCCCGGGCCTGTCACTTCAGAGTTGAGGGGATGAGAGCAGGAGTAGATCTGAGGGGCTAGGAAAGGAGAAGAGAGGTCCCCCCAGGACCCTGCTGGACAGTGAAACACCTGCTGGAGTAAAGCCCACCTGGGCTGCAGCAAGGCCACCTTCTATGGGGTGATGCCCCCATCGCCAGCCCCATAGATGGGAGGTGGGGAGTGGGGGTGGTGACTGCGGGGCACTAGACCACCTGAGGCACAGCTGCCTGCCTGGACAGTTGTGAAGTCCCCCCCCACCCAAATGAGTGGGGAACCCCCACCTCTTTCCCACCTGGACAGTTGTGAAGTACCCCCCACCACCCAGATGAGTGGGGACCCCCCCACCTCTGTCCCGCCTGGACAGTTGCAAAGTCCCCCCGCCCAGATGAGTGGGGACCCCCCCACCTCTGTCCCGCCTGGACAGTTGCGAAGTCCCCCCCGCCCAGATGAGTGGGGACCCCCCCACCTCTGTCCCGCCTGGACAGTTGCAAAGTCCCCCCGCCCAGATGAGTGGGGACCCCCCCACCTCTGTCCCGCCTGGATAGTTGTGAAGTCCCTCCCTGCCCAGATGAGTGGGGACCCCCCCCCAGTCCTGGACTCTGGCAGCAAGGCTCGCTGGGGTCCCTCCGTTCTTACCAGGAATAAAATGCAACATGCAAAGCCCTGCTGTGTGCCCTGCCACTGAGCAGCAAAACAAACAGCAAGAGCAGAGCCCGGCCTGGGACGGGGCAGCTGCAGCTGCAGCCCCTGATGCCAAGCCCTCTGGGACAGGAACTCCCTGGACCCCCGGAACCTGGGGCAGTGGCTAGTTCCTGCCGCCCGCAGGCGTCTCATGGTGCCTCTTGACTTGCAGCGGCCTGGACAGCGCCTCCTGCTTCCAGGTGGTCTCGCTGATGAAAGGGCTCGCTCAAGGGGGTCGCTCCATCATTTGCACCATCCACCAGCCCAGCGCCAAACTCTTCGAGCTGTTCGACCAGGTACGCGGGCCCCGGGCCCTCCCCGCCAGATTACCACTGCACTCAGGTCAGCCTGAATGACACCAAACCCTGGGTA\t*\tSA:Z:chr21,42284027,+,1258S733M,60,1;\tMD:Z:272T73A903A6^ACCCAGATGAGTGGGGACCCCCCACCTCTGTCCTGCCTGGACAGTTGTGAAGTACCCCCCA109A59G4^C48C5C11C24\tRG:Z:GATKSVContigAlignments\tNM:i:72\tAS:i:1354\tXS:i:211", true);
        final List<AlignmentInterval> split = Lists.newArrayList(ContigAlignmentsModifier.splitGappedAlignment(gappedAln, GAPPED_ALIGNMENT_BREAK_DEFAULT_SENSITIVITY, 1991));
        final AlignmentInterval normalAln = fromSAMRecordString("asm029245:tig00000\t2048\tchr21\t42284027\t60\t1258H733M\t*\t0\t0\tCCCAGATGAGTGGGGACCCCCCCACCTCTGTCCCGCCTGGACAGTTGCAAAGTCCCCCCGCCCAGATGAGTGGGGACCCCCCCACCTCTGTCCCGCCTGGACAGTTGCGAAGTCCCCCCCGCCCAGATGAGTGGGGACCCCCCCACCTCTGTCCCGCCTGGACAGTTGCAAAGTCCCCCCGCCCAGATGAGTGGGGACCCCCCCACCTCTGTCCCGCCTGGATAGTTGTGAAGTCCCTCCCTGCCCAGATGAGTGGGGACCCCCCCCCAGTCCTGGACTCTGGCAGCAAGGCTCGCTGGGGTCCCTCCGTTCTTACCAGGAATAAAATGCAACATGCAAAGCCCTGCTGTGTGCCCTGCCACTGAGCAGCAAAACAAACAGCAAGAGCAGAGCCCGGCCTGGGACGGGGCAGCTGCAGCTGCAGCCCCTGATGCCAAGCCCTCTGGGACAGGAACTCCCTGGACCCCCGGAACCTGGGGCAGTGGCTAGTTCCTGCCGCCCGCAGGCGTCTCATGGTGCCTCTTGACTTGCAGCGGCCTGGACAGCGCCTCCTGCTTCCAGGTGGTCTCGCTGATGAAAGGGCTCGCTCAAGGGGGTCGCTCCATCATTTGCACCATCCACCAGCCCAGCGCCAAACTCTTCGAGCTGTTCGACCAGGTACGCGGGCCCCGGGCCCTCCCCGCCAGATTACCACTGCACTCAGGTCAGCCTGAATGACACCAAACCCTGGGTA\t*\tSA:Z:chr21,42282466,+,1257M61D114M1I60M1D63M1I28M467S,60,72;\tMD:Z:513C219\tRG:Z:GATKSVContigAlignments\tNM:i:1\tAS:i:728\tXS:i:0", true);
        split.add(normalAln);
        data.add(new Object[]{split, Arrays.asList(split.get(0), normalAln)});

        return data.toArray(new Object[data.size()][]);
    }

    @Test(groups = "sv", dataProvider = "forTestDeOverlapMultipleAlignments")
    public void testDeOverlapAlignments(final List<AlignmentInterval> alignments,
                                        final List<AlignmentInterval> expectedResults) {
        final List<AlignmentInterval> result = CpxVariantInterpreter.deOverlapAlignments(alignments, bareBoneHg38SAMSeqDict);
        Assert.assertEquals(result, expectedResults);
    }

    // =================================================================================================================

    @Test(groups = "sv")
    public void testTurnIntoVariantContext() throws IOException {
        // test two contigs give the same variant and annotated accordingly
        final CpxVariantInducingAssemblyContig tig13846_3 = new CpxVariantInducingAssemblyContig(new AssemblyContigWithFineTunedAlignments(fromPrimarySAMRecordString("asm013846:tig00003\t0\tchr20\t54849615\t60\t192S49M2I55M1I50M1I246M\t*\t0\t0\tATATTTCTCAGAGGGTCTCTGGGGAGTTGATAGGCTTTGGATGTTTGCCTCCTCCAAATCTCATGTTGAAATGTAATCCCCAGTGTTGGAGGGGGGCAGATCCCTCATGAGTGGCTTGGTGCCCTTCCCATGGTAATGAGTGAGTTCTTGCTCTGTTAGTTCATGAGAGAGCTGATTGTTTAAAGGAGTCTGGCACCTCCTCTCTCTCCTTTCTTCCTCTCTCACCATGTGACACTCCTATCCCCCTTTGCCTTCTTGCCTGAGTAAAAGCTTCCTAAGGCCTCACCAGAAGCCGAGCAGATGCTGTTGCCATGCTTGTAGTCTGCAGAACCATAACCCAAATAAACCCAAGTTTTTATAAATTACCCAGCTTCAGGTATTCCTTGATAGCAACGCAAAATGGATTAACACCTAACCACAGGTGCCCACAGCTGGAACTTGCTCCTTGCCTTATGCTTTGTTGACATTTTTCCCTTCCCTGATTTGCTTTCTTCACTTTCCTCACTCTCTCATTGTGCTTCCTGGAATTATCTCCCAAATAATCAATCTGCACTTACATCCTTTTTATCTCAGGGTCTACTTTTGGAGATACCAAA\t*\tSA:Z:chr20,54849438,+,54M542H,60,0,54;chr15,68774173,+,92H63M441H,60,3,48;\tMD:Z:400\tRG:Z:GATKSVContigAlignments\tNM:i:4\tAS:i:348\tXS:i:0", true)), bareBoneHg38SAMSeqDict);;
        final CpxVariantInducingAssemblyContig tig28220_5 = new CpxVariantInducingAssemblyContig(new AssemblyContigWithFineTunedAlignments(fromPrimarySAMRecordString("asm028220:tig00005\t16\tchr20\t54849438\t60\t54M206S\t*\t0\t0\tATATTTCTCAGAGGGTCTCTGGGGAGTTGATAGGCTTTGGATGTTTGCCTCCTCCAAATCTCATGTTGAAATGTAATCCCCAGTGTTGGAGGGGGGCAGATCCCTCATGAGTGGCTTGGTGCCCTTCCCATGGTAATGAGTGAGTTCTTGCTCTGTTAGTTCATGAGAGAGCTGATTGTTTAAAGGAGTCTGGCACCTCCTCTCTCTCCTTTCTTCCTCTCTCACCATGTGACACTCCTATCCCCCTTTGCCTTCTTGCC\t*\tSA:Z:chr20,54849615,-,192H49M2I17M,60,2,52;chr15,68774173,-,92H63M105H,60,3,48;\tMD:Z:54\tRG:Z:GATKSVContigAlignments\tNM:i:0\tAS:i:54\tXS:i:0", true)), bareBoneHg38SAMSeqDict);
        final CpxVariantCanonicalRepresentation cpxVariantCanonicalRepresentation = new CpxVariantCanonicalRepresentation(tig13846_3);
        final Tuple2<CpxVariantCanonicalRepresentation, Iterable<CpxVariantInducingAssemblyContig>> tuple2 =
                new Tuple2<>(cpxVariantCanonicalRepresentation, Arrays.asList(tig13846_3, tig28220_5));
        final byte[] refBases = b38_reference_chr20_chr21.getReferenceBases(new SimpleInterval("chr20", 54849491, 54849491)).getBases();

        final VariantContextBuilder baseVariantContextBuilder = cpxVariantCanonicalRepresentation.toVariantContext(refBases);
        baseVariantContextBuilder.attribute(GATKSVVCFConstants.TOTAL_MAPPINGS, 2);
        baseVariantContextBuilder.attribute(GATKSVVCFConstants.CONTIG_NAMES, Arrays.asList(tig13846_3.getPreprocessedTig().getContigName(), tig28220_5.getPreprocessedTig().getContigName()));
        baseVariantContextBuilder.attribute(GATKSVVCFConstants.MAPPING_QUALITIES, Arrays.asList("60", "60"));
        baseVariantContextBuilder.attribute(GATKSVVCFConstants.HQ_MAPPINGS, "2");
        baseVariantContextBuilder.attribute(GATKSVVCFConstants.ALIGN_LENGTHS, Arrays.asList("54", "54"));
        baseVariantContextBuilder.attribute(GATKSVVCFConstants.MAX_ALIGN_LENGTH, "54");

        final VariantContext variantContext = CpxVariantInterpreter.toVariantContext(tuple2._1, tuple2._2, b38_reference_chr20_chr21);
        VariantContextTestUtils.assertVariantContextsAreEqual(variantContext, baseVariantContextBuilder.make(), Collections.emptyList(), Collections.emptyList());
    }
}
